<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>类的基本知识</title>
</head>
<body>
  <script>
    /* 
      总结：
        1、类中的构造器不是必须写的，要对实例进行一些初始化的操作，如添加指定属性时，才写
        2、如果A类继承了B类，且A类中写了构造器，那么A类构造器中的super是必须要调用的
        3、类中所定义的方法，都是放在类的原型对象上，供实例去使用
    */
    // 创建一个person类
    class Person {
      // 构造器方法
      constructor(name, age) {
        // 构造器中的this是谁  ——  类的实例对象，即下面我创建的 p1 p2
        this.name = name
        this.age = age
      }
      // 一般方法
      speak() {
        // speak方法放在了Person这个类的原型对象上
        // 通过Person实例调用speak时，speak中的this就是Person实例  **很重要，并不是speak中的this就一定指向Person实例，而是谁调用了speak，this就指向谁，因为call apply bind可以改变this的指向
        console.log(`我叫${this.name},年龄是${this.age}`)
      }
    }

    // 创建一个person的实例对象
    let p1 = new Person('tom', 18)
    let p2 = new Person('jerry', 19)
    console.log(p1)
    console.log(p2)
    p1.speak()
    p1.speak.call({a: 1, b: 2})

    // 创建一个student类，继承于Person类
    class Student extends Person {
      constructor(name, age, grade) {
        super(name, age)      // 必须写super,用super来继承父类的构造器中的内容
        this.grade = grade
      }
      // speak() {
      //   console.log(`我叫${this.name},年龄是${this.age},我的年级是${this.grade}`)
      // }
      study() {
        // study方法放在了哪里？—— 类的原型对象上，供实例使用
        // 通过Student实例调用study时，study中的this就是指向Student实例

        console.log('我很努力的学习')
      }
    }
    const s1 = new Student('小张', 15, '高一')
    console.log(s1)
    s1.speak()

    class Car {
      constructor(name, price) {
        this.name = name
        this.price = price
        this.wheel = 4        // 如果想给每个实例身上都追加同一个属性，值写固定的就行，但没必要写在构造器里面，可以直接写，如下:
      };
      // 类中可以直接赋值语句,如下代码的含义是：给Car的实例对象添加一个属性，名为a，值为1
      // 此时打印c1 c2就是{ a:1, name: "奔驰111", price: 100, wheel: 4 }   {  a:1, name: "奔驰222", price: 200, wheel: 4 }
      a = 1
    }
    const c1 = new Car('奔驰111', 100)
    const c2 = new Car('奔驰222', 200)
    console.log(c1)     // { name: "奔驰111", price: 100, wheel: 4 }
    console.log(c2)     // { name: "奔驰222", price: 200, wheel: 4 }
  </script>
</body>
</html>